HTML-строка яваскриптом

Переодически возникает необходимость добавить много элементов в документ с помощью javascriptа. Если нет необходимости добавлять на каждый элемент событие, то оптимальней вставить элементы строкой в .innerHTML

Обычно получается строка вида:


var html = '<p><span class=' + class_name + '>' + headline + '</span>' + '</p><div class=' + body_class_name + '>' + ... + '</div>';
    

В которой не только можно запутаться, но и дописать туда что-то неудобно.

Один из выходов — описать струкруктуру HTML с помощью JSON:


var tHtml = {
    para: {
        name: 'p',
        sClass: 'note',
        content: [
            'text',
            ' and some text'
        ]
    },
    list: {
        name: 'ul',
        sClass: 'list',
        content: [
            '<li>from string</li>',
            {
                name: 'li',
                content: [
                    'generated'
                ]
            },
            {
                name: 'li',
                content: [
                    {
                        name: 'strong',
                        content: ['bold font']
                    },
                    ' and normal'
                ]
            }
        ]
    }
}

    

Сгенерировалось:

Чтобы использовать шаблон, надо:


var hgen = new HtmlGen();
hgen.generate({
    id: 'example', // id html элемента
    template: tHtml // шаблон
});

    

Класс (или тип) HtmlGen:


function HtmlGen(){
    
}
HtmlGen.prototype = {
    generate: function(o){
        $(o.id).innerHTML = this.template_to_string(o.template);
    },
    /**
     * Обрабатываем шаблон
     */
    template_to_string: function(template){

        var output = '';

        for(x in template){
            output += this.tag_to_string(template[x], x);
        }
        return output;
    },
    /**
     * Обрабатываем содержимое "тега"
     */
    content_to_string: function(content){
        var output = '';
        for(var i=0; i < content.length; i++){
            if(typeof content[i] == "string") output += content[i];
            if(typeof content[i] == "object") output += this.tag_to_string(content[i]);
        }
        return output;
    },
    /**
     * Превратить "тег" в строку
     */
    tag_to_string: function(tag, name){
        // TODO аттрибуты
        return '<' + tag.name + this.attributes(tag) + '>' + (tag.content ? this.content_to_string(tag.content) : '') + '</' + tag.name + '>';
    },
    /**
     * Работаем с атрибутами
     */
    attributes: function(tag){
        var output = '';
        for(x in this.attrCollection){
            if(tag[x]) output += ' ' + this.attrCollection[x] + '="' + tag[x] + '"';
        }
        return output;
    },
    /**
     * Коллекция аттрибутов
     */
    attrCollection: {
        sClass: 'class',
        sSrc: 'src'
    }
}
    

В attrCollection добавляем по необходимости нужные аттрибуты: src, title, alt и др. В дальнейшем у шаблона можно легко менять структуру, добавлять аттрибуты и т.п.

К этому классу можно добавить возможность не только, вставлять html-строку, но и добавлять через append с событиями и прочим.

Походу написания HtmlGen у IE обнаружилась забавная фича: если написать for(item in some_object){...}, то будет ошибка, а если написать for(x in some_object){...}, то ошибка исчезнет. Похоже «item» зарезервированное слово.